package cn.fl.customer.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;

import cmm.comm.facade.framework.api.ISysDictionaryApiService;
import cmm.mid.core.framework.page.KeyValueVO;
import cmm.mid.core.framework.page.Pager;
import cn.cmm.base.framework.constant.BaseConstant;
import cn.cmm.base.framework.constant.BaseExceptionConstant;
import cn.cmm.base.framework.exception.BaseException;
import cn.cmm.base.framework.utils.BaseLogUtils;
import cn.cmm.base.framework.utils.CollectionUtils;
import cn.cmm.base.framework.utils.StringUtils;
import cn.cmm.cache.framework.utils.PropertiesCacheUtils;
import cn.fl.customer.service.ICstBankService;
import cn.fl.customer.transform.CstBankVOTransform;
import cn.fl.customer.vo.CstBankVO;
import cn.fl.framework.base.context.CurrentThreadContext;
import cn.fl.framework.constant.DictionaryConstant;
import fl.customer.facade.customer.api.ICustomerApiService;
import fl.customer.facade.customer.api.ICustomerModifyApiService;
import fl.customer.facade.customer.api.ICustomerQueryApiService;
import fl.customer.facade.customer.condition.CstBankQueryCondition;
import fl.customer.facade.customer.condition.CstBscInfoQueryCondition;
import fl.customer.facade.customer.dto.CstBankDTO;
import fl.customer.facade.customer.dto.CstBscInfoDTO;

@Service
public class CstBankServiceImpl implements ICstBankService {

	/**
	 * 日志
	 */
	private static final Logger logger = LoggerFactory.getLogger(CstBankServiceImpl.class);
	
	/**
	 * 客户API服务
	 */
	@Autowired
	private ICustomerApiService customerApiService;
	
	/**
	 * 本地数据字典
	 */
	@Autowired
	private ISysDictionaryApiService sysDictionaryApiService;
	
	/**
	 * 客户查询API
	 */
	@Autowired
	private ICustomerQueryApiService customerQueryApiService;
	
	/**
	 * 客户修改API服务
	 */
	@Autowired
	private ICustomerModifyApiService customerModifyApiService;

	@Override
	public CstBankVO selectById(Long id) {
		if(StringUtils.isEmpty(id))return null;
		CstBankDTO dto = this.customerApiService.selectCstBankById(id);
		List<CstBankDTO> dtoList = new ArrayList<CstBankDTO>();
		dtoList.add(dto);
		this.setDicInfo(dtoList);
		CstBankDTO cstBankDTO = dtoList.get(0);
		return CstBankVOTransform.toVO(cstBankDTO);
	}

	@Override
	public Long add(CstBankVO entity) {
		if(null == entity)return null;
		//先判断有没有数据,如果有则提示已经存在-根据开户银行、开户名称、银行帐号
		CstBankQueryCondition qc = new CstBankQueryCondition();
		List<String> accNmList = new ArrayList<>();
		accNmList.add(entity.getAccNm());
		List<String> accNoList = new ArrayList<>();
		accNoList.add(entity.getAccNo());
		//List<Long> cstIdList = new ArrayList<>();
		//cstIdList.add(entity.getCstId());
		qc.setAccNmList(accNmList);
		qc.setAccNoList(accNoList);
		qc.setBkCd(entity.getBkCd());
		//qc.setCstIdList(cstIdList);
		List<CstBankDTO> list = this.customerQueryApiService.searchCstBankList(qc);
		if(CollectionUtils.isNotEmpty(list)){
			//如果查询到该卡属于客户本身则提示银行卡已存在不能在添加,如果是有其它客户已经加了这个卡则提示"已经有其它客户拥有此卡,不能添加。"
			Long cstId = entity.getCstId();
			boolean tip = false;
			Long cstIdTmp = null;
			for (CstBankDTO cstBankDTO : list) {
				cstIdTmp = cstBankDTO.getCstId();
				if(!cstId.equals(cstIdTmp)){
					tip = true;
					break;
				}
			}
			
			if(tip){
				BaseLogUtils.info(logger, "add", "此卡已经被其他客户绑定!CST_ID:"+cstIdTmp + "->查询参数：" + JSON.toJSONString(qc));
				throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_604, "此卡已经被其他客户绑定,不能添加!");
			}
			BaseLogUtils.info(logger, "add", "此卡已经存在!" + JSON.toJSONString(qc));
			throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_604, "银行卡已经存在不能重复添加!");
		}
		return this.customerApiService.addCstBank(CstBankVOTransform.toDTO(entity));
	}

	@Override
	public boolean removeByIds(List<Long> ids) {
		if(CollectionUtils.isEmpty(ids))return false;
		//先查询,如果是验证通过状态则不能删除
		CstBankQueryCondition cstBankQueryCondition = new CstBankQueryCondition();
		cstBankQueryCondition.setIdList(ids);
		List<CstBankDTO> list = this.customerQueryApiService.searchCstBankList(cstBankQueryCondition);
		if(CollectionUtils.isNotEmpty(list)){
			String passStatus = PropertiesCacheUtils.getProperty(fl.constant.facade.framework.constant.DictionaryConstant.CODE_GRP_VALID_STATUS_CD_B);
			StringBuffer sb = new StringBuffer();
			for (CstBankDTO cstBankDTO : list) {
				String audStsCd = cstBankDTO.getAudStsCd();
				
				if(passStatus.equals(audStsCd)){
					sb.append(cstBankDTO.getAccNm());
					sb.append("; ");
				}
			}
			
			//说明有提示内容
			if(StringUtils.isNotEmpty(sb.toString())){
				BaseLogUtils.info(logger, "removeByIds", "有已经验证过的数据不能删除!" + sb.toString());
				throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_604, sb.toString()+" 银行卡验证通过不能删除,请刷新页面!");
			}
		}
		
		return this.customerApiService.removeCstBankIds(ids);
	}

	@Override
	public boolean batchModify(List<CstBankVO> list) {
		if(CollectionUtils.isEmpty(list))return false;
		return this.customerApiService.batchModifyCstBank(CstBankVOTransform.toDTOList(list));
	}

	@SuppressWarnings("unchecked")
	@Override
	public Pager searchListPage(Pager page) {
		if(null == page)page = new Pager();
		Pager pager = this.customerApiService.searchCstBankPage(page);
		List<CstBankDTO> list = (List<CstBankDTO>) pager.getResultList();
		
		this.setCstBankForCstBacInfo(list);
		this.setDicInfo(list);
		pager.setResultList(CstBankVOTransform.toVOList(list));
		return pager;
	}

	@Override
	public boolean batchAdd(List<CstBankVO> list) {
		if(CollectionUtils.isEmpty(list))return false;
		return this.customerApiService.batchAddCstBank(CstBankVOTransform.toDTOList(list));
	}

	@Override
	public boolean modify(CstBankVO entity) {
		if(null == entity)return false;
		//先判断有没有数据,如果有则提示已经存在-根据开户银行、开户名称、银行帐号
		CstBankQueryCondition qc = new CstBankQueryCondition();
		List<String> accNmList = new ArrayList<>();
		accNmList.add(entity.getAccNm());
		List<String> accNoList = new ArrayList<>();
		accNoList.add(entity.getAccNo());
		//List<Long> cstIdList = new ArrayList<>();
		//cstIdList.add(entity.getCstId());
		qc.setAccNmList(accNmList);
		qc.setAccNoList(accNoList);
		qc.setBkCd(entity.getBkCd());
		//qc.setCstIdList(cstIdList);
		List<CstBankDTO> list = this.customerQueryApiService.searchCstBankList(qc);
		Boolean pass = true;
		if (CollectionUtils.isNotEmpty(list)) {
			Long cstId = entity.getCstId();
			boolean tip = false;
			boolean cannotTip = false;//是否可以修改
			Long cstIdTmp = null;
			String passStatus = PropertiesCacheUtils.getProperty(fl.constant.facade.framework.constant.DictionaryConstant.CODE_GRP_VALID_STATUS_CD_B);
			
			for (CstBankDTO cstBankDTO : list) {
				
				if(passStatus.equals(cstBankDTO.getAudStsCd())){//如果已经是验证状态则不能修改
					cannotTip = true;
					break;
				}
				
				cstIdTmp = cstBankDTO.getCstId();
				if(!cstId.equals(cstIdTmp)){//如果卡已经被其他客户使用,则不能修改
					tip = true;
					break;
				}
				
				Long id = cstBankDTO.getId();
				if(!id.equals(entity.getId())){//卡在自己名下且已经非本条数据则提示不能修改
					pass = false;
					break;
				}
			}
			
			if(cannotTip){
				BaseLogUtils.info(logger, "modify", "此卡已验证不能修改!CST_ID:"+cstIdTmp + "->查询参数：" + JSON.toJSONString(qc));
				throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_604, "此卡已验证不能修改!");
			}
			
			if(tip){
				BaseLogUtils.info(logger, "modify", "此卡已经被其他客户绑定!CST_ID:"+cstIdTmp + "->查询参数：" + JSON.toJSONString(qc));
				throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_604, "此卡已经被其他客户绑定,不能再绑定!");
			}
			
			if(!pass){
				BaseLogUtils.info(logger, "modify", "修改时此卡已经存在!" + JSON.toJSONString(qc));
				throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_604, "银行卡已经存在不能修改!");
			}
		}
		return this.customerApiService.modifyCstBankDTO(CstBankVOTransform.toDTO(entity));
	}

	@Override
	public List<KeyValueVO> searchBkCdList() {
		return this.sysDictionaryApiService.getKvList(DictionaryConstant.CODE_GRP_CST_NP_BK_CD, CurrentThreadContext.getCurrentSysCd(), CurrentThreadContext.getCurrentOrgCd());
	}

	@Override
	public List<KeyValueVO> searchAccTypCdList() {
		return this.sysDictionaryApiService.getKvList(DictionaryConstant.CODE_GRP_CST_NP_ACC_TYP_CD, CurrentThreadContext.getCurrentSysCd(), CurrentThreadContext.getCurrentOrgCd());
	}

	@Override
	public List<KeyValueVO> searchYesOrNoList() {
		return this.getYesOrNo();
	}
	/**
	 * 是否前端显示
	 * @return
	 */
	private List<KeyValueVO> getYesOrNo(){
		return this.sysDictionaryApiService.getKvList(DictionaryConstant.CODE_SYS_YES_NO_CD, CurrentThreadContext.getCurrentSysCd(), CurrentThreadContext.getCurrentOrgCd());
	}
	
	/**
	 * 设置数据字典项目
	 * @param dto
	 */
	private void setDicInfo(List<CstBankDTO> list){
		if(CollectionUtils.isEmpty(list))return;
		Map<String, String> accTypCdMap = null;
		Map<String, String> audStsCdMap = null;
		Map<String, String> certTypCdMap = null;
		Map<String, String> bkCdMap = null;
		Map<String, String> audStsCdRemMap = null;
		Map<String, String> regWayCdMap = null;
		Map<String, String> cardTypCdMap = null;
		String sysCd = CurrentThreadContext.getCurrentSysCd();
		String orgCd = CurrentThreadContext.getCurrentOrgCd();
		try {
			String regWayCd = PropertiesCacheUtils.getProperty(fl.constant.facade.framework.constant.DictionaryConstant.CODE_CST_BANK_REG_WAY_CD);
			String cardTypCd = PropertiesCacheUtils.getProperty(fl.constant.facade.framework.constant.DictionaryConstant.CODE_CST_BANK_CART_TYPE_CD);
			List<String> codeGrpCdList = new ArrayList<>();
			codeGrpCdList.add(DictionaryConstant.CODE_GRP_CST_NP_ACC_TYP_CD);
			codeGrpCdList.add(DictionaryConstant.CODE_GRP_VALID_STATUS_CD);
			codeGrpCdList.add(DictionaryConstant.CODE_GRP_CERT_TYP_CD);
			codeGrpCdList.add(DictionaryConstant.CODE_GRP_CST_NP_BK_CD);
			codeGrpCdList.add(DictionaryConstant.CODE_GRP_BACK_AUD_STS_CD_REM);
			codeGrpCdList.add(regWayCd);
			codeGrpCdList.add(cardTypCd);
			Map<String, Map<String, String>>  resultMap = this.sysDictionaryApiService.searchMultiGroupToMap(sysCd, orgCd, codeGrpCdList);
			accTypCdMap = resultMap.get(DictionaryConstant.CODE_GRP_CST_NP_ACC_TYP_CD);
			audStsCdMap = resultMap.get(DictionaryConstant.CODE_GRP_VALID_STATUS_CD);
			certTypCdMap = resultMap.get(DictionaryConstant.CODE_GRP_CERT_TYP_CD);
			bkCdMap = resultMap.get(DictionaryConstant.CODE_GRP_CST_NP_BK_CD);
			audStsCdRemMap = resultMap.get(DictionaryConstant.CODE_GRP_BACK_AUD_STS_CD_REM);
			regWayCdMap = resultMap.get(regWayCd);
			cardTypCdMap = resultMap.get(cardTypCd);
		}catch (BaseException e) {
			BaseLogUtils.info(logger, "setDicInfo", "获取数据字典失败!"+e.getMessage());
		}catch (Exception e) {
			BaseLogUtils.error(logger, "setDicInfo", "获取数据字典失败!"+e.getMessage());
		}finally {
			if(CollectionUtils.isMapEmpty(accTypCdMap)){
				accTypCdMap = new HashMap<>();
			}
			if(CollectionUtils.isMapEmpty(audStsCdMap)){
				audStsCdMap = new HashMap<>();
			}
			if(CollectionUtils.isMapEmpty(certTypCdMap)){
				certTypCdMap = new HashMap<>();
			}
			if(CollectionUtils.isMapEmpty(bkCdMap)){
				bkCdMap = new HashMap<>();
			}
			if(CollectionUtils.isMapEmpty(audStsCdRemMap)){
				audStsCdRemMap = new HashMap<>();
			}
			if(CollectionUtils.isMapEmpty(regWayCdMap)){
				regWayCdMap = new HashMap<>();
			}
			if(CollectionUtils.isMapEmpty(cardTypCdMap)){
				cardTypCdMap = new HashMap<>();
			}
		}
		
		Map<Integer, String> ynMap = BaseConstant.getYesNoMap;
		for (CstBankDTO cstBankDTO : list) {
			if(accTypCdMap.containsKey(cstBankDTO.getAccTypCd())){
				cstBankDTO.setAccTypCdNm(accTypCdMap.get(cstBankDTO.getAccTypCd()));
			}
			
			if(audStsCdMap.containsKey(cstBankDTO.getAudStsCd())){
				cstBankDTO.setAudStsCdNm(audStsCdMap.get(cstBankDTO.getAudStsCd()));
			}
			
			if(certTypCdMap.containsKey(cstBankDTO.getCertTypCd())){
				cstBankDTO.setCertTypCdNm(certTypCdMap.get(cstBankDTO.getCertTypCd()));
			}
			
			if(bkCdMap.containsKey(cstBankDTO.getBkCd())){
				cstBankDTO.setBkCdNm(bkCdMap.get(cstBankDTO.getBkCd()));
			}
			
			if(audStsCdRemMap.containsKey(cstBankDTO.getAudStsCdRem())){
				cstBankDTO.setAudStsCdRem(audStsCdRemMap.get(cstBankDTO.getAudStsCdRem()));
			}
			
			if(regWayCdMap.containsKey(cstBankDTO.getRegWayCd())){
				cstBankDTO.setRegWayCdNm(regWayCdMap.get(cstBankDTO.getRegWayCd()));
			}
			
			if(cardTypCdMap.containsKey(cstBankDTO.getCardType())){
				cstBankDTO.setCardTypeNm(cardTypCdMap.get(cstBankDTO.getCardType()));
			}
			
			if(cstBankDTO.getIsDeduct()!=null){
				cstBankDTO.setIsDeductNm(ynMap.get(cstBankDTO.getIsDeduct()));
			}
			if(cstBankDTO.getIsValid()!=null){
				cstBankDTO.setIsValidNm(ynMap.get(cstBankDTO.getIsValid()));
			}
			if(cstBankDTO.getIsInsBind() !=null){
				cstBankDTO.setIsInsBindNm(ynMap.get(cstBankDTO.getIsInsBind()));
			}
		}
	}

	@Override
	public boolean modifyAudStsCd(Long id, String validSts, String accRem) throws BaseException {
		return this.customerApiService.modifyAudStsCd(id, validSts, accRem, new Date(),
				CurrentThreadContext.getCurrentUserId());
	}

	@Override
	public List<CstBankVO> searchList(CstBankQueryCondition qc) throws BaseException {
		List<CstBankDTO> list = this.customerQueryApiService.searchCstBankList(qc);
		this.setCstBankForCstBacInfo(list);
		this.setDicInfo(list);
		return CstBankVOTransform.toVOList(list);
	}

	/**
	 * 设置用户的基础信息
	 * @param list
	 */
	private void setCstBankForCstBacInfo(List<CstBankDTO> list) {
		if(CollectionUtils.isNotEmpty(list)){
			List<Long> cstIdList = new ArrayList<>();
			String passStatus = PropertiesCacheUtils.getProperty(fl.constant.facade.framework.constant.DictionaryConstant.CODE_GRP_VALID_STATUS_CD_B);
			for (CstBankDTO cstBankDTO : list) {
				//如果是验证过的则前台不能修改不能删除
				String audStsCd = cstBankDTO.getAudStsCd();
				if(passStatus.equals(audStsCd)){
					cstBankDTO.setIsOper(false);
				}else{
					cstBankDTO.setIsOper(true);
				}
				Long cstId = cstBankDTO.getCstId();
				if(cstIdList.contains(cstId))continue;
				cstIdList.add(cstId);
			}
			
			CstBscInfoQueryCondition condition = new CstBscInfoQueryCondition();
			condition.setIds(cstIdList);
			List<CstBscInfoDTO> cstList = this.customerQueryApiService.searchCstBscInfoList(condition);
			if(CollectionUtils.isNotEmpty(cstList)){
				Map<Long, CstBscInfoDTO> map = new HashMap<>();
				for (CstBscInfoDTO cstBscInfoDTO : cstList) {
					map.put(cstBscInfoDTO.getId(), cstBscInfoDTO);
				}
				
				CstBscInfoDTO cstBscInfoDTO = null;
				for (CstBankDTO cstBankDTO : list) {
					Long cstId = cstBankDTO.getCstId();
					if(map.containsKey(cstId)){
						cstBscInfoDTO = map.get(cstId);
						if(null != cstBscInfoDTO){
							cstBankDTO.setCstNm(cstBscInfoDTO.getCstNm());
							//如果是验证通过的则不按照审核标识处理ISOper,因为在上面已经最终确定了
							String audStsCd = cstBankDTO.getAudStsCd();
							if(passStatus.equals(audStsCd)){
								continue;
							}
							//加入一个是否审核通过标识
							/*if(FlowConstant.FLOW_CHECK_STATE_PASS.equals(cstBscInfoDTO.getAudStsCd())){
								cstBankDTO.setIsOper(false);//不可以修改删除操作
							}else{
								cstBankDTO.setIsOper(true);//可以修改删除操作
							}*/
						}
					}
				}
			}
		}
	}

	@Override
	public boolean importCstBank(List<CstBankVO> list) throws BaseException {
		return this.customerModifyApiService.importCstBank(CstBankVOTransform.toDTOList(list));
	}

	@Override
	public boolean modifyIsDeduct(Long id, Integer isDeduct, Integer isDefDeduct, String audStsCd, Integer isValid, Long mdfUsrId) throws BaseException {
		if(StringUtils.isEmpty(id)){
			BaseLogUtils.info(logger, "modifyIsDeduct", "主键不能为空!" , CurrentThreadContext.getCurrentUserName());
			throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_600, "主键不能为空!");
		}
		
		if(StringUtils.isEmpty(isDeduct)){
			BaseLogUtils.info(logger, "modifyIsDeduct", "是否代扣卡不能为空!" , CurrentThreadContext.getCurrentUserName());
			throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_600, "是否代扣卡不能为空!");
		}
		return this.customerModifyApiService.modifyIsDeduct(id, isDeduct, isDefDeduct,audStsCd,isValid, mdfUsrId);
	}

	@Override
	public boolean modifyIsValid(Long id, String isValid) throws BaseException {
		Long mdfUsrId = CurrentThreadContext.getCurrentUserId();
		return this.customerModifyApiService.modifyValidSts(id, isValid, new Date(), mdfUsrId);
	}
	
	@Override
	public void modifyCstBkCd() throws BaseException {
		this.customerApiService.noTransModifyCstBkCd();
	}
}
